✅@2022-04-13 水理学の教科書をscrapbox書籍にする
作成方法
入力
Gyazoのpermalinkが入った配列
これは手元にある
uploadするだけ
節見出しとページ番号との対応
ここまでやらなくていいしやる時間もないので、省略したものを作り直す
以前やったときは、冒頭十数ページしか作成できなかったようだ
出力
書式はmakePage()で決める
2022-04-13
15:41:43 おしまい。あとは読みながら編集する
15:31:09 作成完了
当然だがprivate
見出しとページ番号との対応
ページ番号は表紙含めて0から始める
scriptの都合上、見出しに,が混じらないようにする
table:index
カバー 0
表紙裏 1
表紙 2
執筆者一覧 3
まえがき 6
目次 7
1.1 水理学とは? 8
1.2 本書のねらいと構成 9
1.3 次元・単位・有効数字 11
1.4 流体の性質 15
1.5 流れの分類 18
2.1 なぜ「静水力学」を学ぶのか? 20
2.2 静水圧 23
2.3 浮力とアルキメデスの原理 25
2.4 平面と曲面に働く静水圧 34
2.5 浮体の安定・不安定 43
3.1 水の持つエネルギー 45
3.2 ベルヌーイの定理の導出 48
3.3 流管におけるエネルギーの流入・流出と仕事の関係による導出 51
3.4 ベルヌーイの定理を使ったトリチェリーの定理 53
3.5 ベルヌーイの定理の応用例 71
4.1 なぜ「運動量保存則」を学ぶのか? 73
4.2 運動量保存則の導出 76
4.3 運動量保存則の応用 93
5.1 はじめに 94
5.2 流体運動の記述方法 95
5.3 流体運動の基礎方程式 100
5.4 ナビエ・ストークスの式,連続式の導出 106
5.5 流体の基本運動要素と渦度 109
5.6 速度ポテンシャルと流関数 112
6.1 層流・乱流の性質 114
6.2 レイノルズ数 116
6.3 限界レイノルズ数 117
6.4 層流の流速分布―円管路の場合 120
6.5 乱流とレイノルズ応力 123
6.6 乱流の流速分布―壁面近傍の流れ― 133
7.1 管路流れとは? 134
7.2 管路流れの基礎式 136
7.3 摩擦損失 140
7.4 摩擦損失以外の損失 146
7.5 管路の損失計算 157
8.1 開水路流れとは? 161
8.2 フルード数と常流・射流 165
8.3 比エネルギー 168
8.4 開水路の断面変化に伴う水面形 175
8.5 比力 182
9.1 等流とは? 183
9.2 等流における摩擦抵抗 185
9.3 平均流速公式 191
9.4 等流水深と限界勾配 197
10.1 漸変流とは? 198
10.2 基礎式 202
10.3 基本的な水面形 205
10.4 水面形の出現例 209
11.1 水理模型実験と相似則 210
11.2 幾何学的相似と力学的相似 214
11.3 フルード相似則 216
11.4 レイノルズ相似則 219
演習問題解答 237
索引 239
出版情報 240
広告 241
裏表紙 242
code:sh
code:script.ts
import { getImage } from "../deno-gyazo/mod.ts";
import { getGyazoToken } from "../scrapbox-userscript-std/rest.ts";
import { useStatusBar } from "../scrapbox-userscript-std/dom.ts";
import { pool, sort } from "../async-lib/mod.ts";
import { upload } from "../scrapbox-file-uploader/mod.ts";
import { makePage, makePageInit } from "./makePage.ts";
import { makeSectionMap } from "./section.ts";
// 読み込み
const pending = fetch("/api/table/takker/『第3版_土質力学』/index.csv");
const file = await upload({ accept: "application/json, *.json"});
if (!file) throw new Error("no file specified");
// データ形成
const table = await (await pending).text();
const sectionMap = makeSectionMap(table);
const gyazoList = JSON.parse(await file.text()) as string[];
console.info(sectionMap);
console.log(gyazoList);
type Gyazo = { url: string; text: string; index: number; };
const result = await getGyazoToken();
if (!result.ok) throw new Error(JSON.stringify(result.value));
const accessToken = result.value;
if (!accessToken) throw new Error("Could not get the access token");
const { render, dispose } = useStatusBar();
// OCR取得
const reader = pool(
5,
Array(gyazoList.length).keys(),
async (index: number): Promise<Gyazo> => {
const gyazo = gyazoListindex; const id = gyazo.match(/\/(^\/+)$/)?.1; if (!id) throw new Error(Could not find Gyazo ID from "${gyazo}");
const result = await getImage(id, { accessToken });
if (!result.ok) throw new Error(JSON.stringify(result.ok));
const { permalink_url, ocr } = result.value;
return { url: permalink_url, text: ocr?.description || "", index, };
},
);
const pages = [] as { title: string; lines: string[]; }[];
const stack = [] as makePageInit[];
let counter = 0;
for (const promise of reader) {
const result = await promise;
if (!result.success) throw new Error(JSON.stringify(result.reason));
const { url, text, index } = result.value;
// データを取得しながらページを作る
const data = {
pageNum: counter,
text: text,
gyazo: url,
};
stack.push(data);
if (stack.length === 2) {
pages.push(makePage({
nextSection: stack1.section, }));
counter++;
} else if (stack.length === 3) {
pages.push(makePage({
prevSection: stack0.section, nextSection: stack2.section, }));
stack.shift();
counter++;
} else {
counter++;
}
render(
{ type: "spinner" },
{
type: "text",
text: ${gyazoList.length} images, ${counter} got,
},
);
}
dispose();
// 最後のページ
pages.push(makePage({
prevSection: stack0.section, }));
// download
console.log(pages);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "import.json";
a.click();
URL.revokeObjectURL(url);
以下の書式でページを作る
code:title
${section} ${page}
code:body
OCRした本文
<=${prev}|${next}=>
${gyazo_url}
末尾に節へのリンクをつけて、同じ節のページを一覧できるようにする
編集しやすくするため
code:makePage.ts
export interface makePageInit {
section: string;
gyazo: string;
text: string;
/** ページ番号 */
pageNum: number;
prevSection?: string;
nextSection?: string;
}
export const makePage = (init: makePageInit): { title: string; lines: string[]; } => {
const {
section,
gyazo,
text,
pageNum,
prevSection,
nextSection,
} = init;
const title = ${format(section)} ${pageNum};
const prevTitle = prevSection ? ${format(prevSection)} ${pageNum - 1} : undefined;
const nextTitle = nextSection ? ${format(nextSection)} ${pageNum + 1} : undefined;
return {
title,
lines: [
title,
...format(text).split("\n"),
"",
`<=${
prevTitle ? [${prevTitle}] : ""
}|${
nextTitle ? [${nextTitle}] : ""
}=>`,
"",
[${gyazo}],
[${section}],
],
};
}
const format = (text: string): string =>
text
.replace(/\s+$/, "") // 末尾の余計な空白を消す
.replace(/^(\s*)・/, "$1 ") // ・を箇条書きに変える
.replace(
(s) => String.fromCharCode(s.charCodeAt(0) - 0xFEE0),
) // 全角英数を半角に直す
.replace(/\s?\[/g, "[") // リンク記法をescapeする
.replace(/\s?\[/g, "[")
.replace(/(\d+).\s*/g, "$1. ") // 番号付き箇条書きにする
.replaceAll(".", "。") // 句読点を変換する
.replaceAll(",", "、");
csvから、ページ番号と見出しとの対応配列を作る
code:section.ts
export const makeSectionMap = (csv: string): string[] => {
const data = csv.split("\n").map((row) => row.split(","));
const sections = [] as string[];
while (sections.length <= parseInt(end)) {
sections.push(section);
}
}
return sections
};